#include <sstream>
#include <string>
#include <boost/shared_ptr.hpp>
#include <jni.h>
#include "zinnia.h"

using namespace std;

static boost::shared_ptr<zinnia::Recognizer> recognizer;

JNIEXPORT jbyteArray JNICALL Java_tv_dyndns_kishibe_server_handwriting_RecognizerZinnia_recognize(JNIEnv * env, jobject obj, jintArray a, jintArray b, jintArray c)
{
	if (recognizer == NULL){
		recognizer = boost::shared_ptr<zinnia::Recognizer>(zinnia::Recognizer::create());
		if (!recognizer->open("/usr/local/lib/zinnia/model/tomoe/handwriting-ja.model")){
			return NULL;
		}
	}

	jsize length = env->GetArrayLength(a);
	jint* aa = env->GetIntArrayElements(a, NULL);
	jint* bb = env->GetIntArrayElements(b, NULL);
	jint* cc = env->GetIntArrayElements(c, NULL);

	zinnia::Character* character = zinnia::Character::create();
	character->clear();
	character->set_width(300);
	character->set_height(300);

	for (int i = 0; i < length; ++i){
		character->add(aa[i], bb[i], cc[i]);
	}

	env->ReleaseIntArrayElements(c, cc, 0);
	env->ReleaseIntArrayElements(b, bb, 0);
	env->ReleaseIntArrayElements(a, aa, 0);
	cc = NULL;
	bb = NULL;
	aa = NULL;

	ostringstream oss;

	{
		zinnia::Result *result = recognizer->classify(*character, 12);
		if (!result) {
			return NULL;
		}

		for (size_t i = 0; i < result->size(); ++i) {
			oss << result->value(i);
		}
		delete result;
		result = NULL;
	}

	delete character;
	character = NULL;

	jbyteArray result = env->NewByteArray(oss.str().size());
	if (result == NULL){
		return NULL;
	}

	jbyte* buffer = env->GetByteArrayElements(result, NULL);
	if (buffer == NULL){
		env->ReleaseByteArrayElements(result, buffer, 0);
		return NULL;
	}

	memcpy(buffer, oss.str().c_str(), oss.str().size());

	env->ReleaseByteArrayElements(result, buffer, 0);
	buffer = NULL;

	return result;
}
